package ec.edu.ups.cidi.siia.plamdep.webcrawler.descarga;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;

import ec.edu.ups.cidi.siia.plamdep.configuracion.ConfiguracionConexionWeb;
import ec.edu.ups.cidi.siia.plamdep.utils.Log;

import java.util.zip.GZIPInputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
public class DescargarFuente 
{
	private static int timeoutConnection=8000;
	private static String userAgent="Firefox/21.0";
	private HttpURLConnection conHttp=null;
	private HttpsURLConnection conHttps=null;

    public  DescargarFuente ()
    {
        //SetearConfiguraciones
        if( ConfiguracionConexionWeb.htppProxy.length()>0&&ConfiguracionConexionWeb.htppPort.length()>0)
        {   System.setProperty("http.proxyHost",ConfiguracionConexionWeb.htppProxy);
            System.setProperty("http.proxyPort",ConfiguracionConexionWeb.htppPort);
        }
        if( ConfiguracionConexionWeb.htppsProxy.length()>0&&ConfiguracionConexionWeb.htppsPort.length()>0)
        {    
            System.setProperty("https.proxyHost", ConfiguracionConexionWeb.htppsProxy);
            System.setProperty("https.proxyPort",ConfiguracionConexionWeb.htppsPort);
        }
    }
 
  
    public InputStream descargarAsInputStream(String link)
    {
        link=this.validarProtocolo(link);
        if(link.startsWith("https")) return this.descargaHTTPSGET(link,null);
        return this.descargaHTTPGET(link);
    }
    
    
     
    /**
     * Valida y reconstruye el link en un formto adecuado
     * @param link
     * @return 
     */
    public String validarProtocolo(String link)
    {
        if(link.startsWith("http")==false) link="http://"+link;
        return link;
    }
   
    /**
     * Obtiene el tipo de contenido al que hace referencia un link (pagina,documento,etc..)
     * @param link link a buscar
     */
    public String getTipoContenido(String link)
    {   
    	String contenido="";
    	try{
        link=this.validarProtocolo(link);
        if(link.startsWith("http")) 
        {
             java.net.URL url = new java.net.URL(link);
             java.net.URLConnection con = url.openConnection();
             contenido= con.getContentType();
        }            
       else 
       { 
          java.net.URL url = new java.net.URL(link);
          HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
          conHttp.setConnectTimeout(timeoutConnection);
          conHttp.setReadTimeout(timeoutConnection);
          contenido=con.getContentType();
          con.disconnect();
       }
       }
    	catch(java.net.SocketTimeoutException timeoutError)
    	{
    		Log.log(null,Log.MOD_WEBCRAWLER,Log.LEVEL_ERROR, DescargarFuente.class,"Error timeout de conexion.....");
    		 return "text/html; charset=utf-8";
    	}
    	catch(Exception ex)
       {
    	   Log.log(ex,Log.MOD_WEBCRAWLER,Log.LEVEL_ERROR, DescargarFuente.class,"Error al obtener el tipo de contenido.....");
       }
    	if(contenido!=null)
    		return contenido;
        return "text/html; charset=utf-8";
    }
     private InputStream descargaHTTPGET(String link)
    {   InputStream is=null; 
    	 
         try{   java.net.URL url = new java.net.URL(link);
         		conHttp=(HttpURLConnection)url.openConnection();
         		conHttp.setRequestProperty("User-agent",userAgent);
                conHttp.setRequestProperty("Accept-Encoding", "gzip, deflate");
                conHttp.setConnectTimeout(timeoutConnection);
                conHttp.setReadTimeout(timeoutConnection);
                
                
                
                
                String encoding = conHttp.getContentEncoding();
                if (encoding != null && encoding.equalsIgnoreCase("gzip")) is=(new GZIPInputStream(conHttp.getInputStream()));
                else if (encoding != null && encoding.equalsIgnoreCase("deflate")) is=(new InflaterInputStream(conHttp.getInputStream(),new Inflater(true)));
                else    is=(conHttp.getInputStream());
            }
         catch(java.net.SocketTimeoutException timeoutError)
     	{
     		Log.log(null,Log.MOD_WEBCRAWLER,Log.LEVEL_ERROR, DescargarFuente.class,"Error timeout de conexion.....");
    		return null;

     	}
         catch(Exception e)
            {
            	Log.log(e,Log.MOD_WEBCRAWLER,Log.LEVEL_ERROR, DescargarFuente.class,"Error en descarga HTTP");  
            }
         	finally
			{
         		
				
			}
        return is;
    }
    private InputStream descargaHTTPSGET(String link,Map<String, Object>params)
    {
    	try {
                java.net.URL url = new java.net.URL(link);
                conHttps = (HttpsURLConnection)url.openConnection();
                
                if(params!=null)
                {	
	                Iterator<String> it = params.keySet().iterator();
	              	String param=null;
	              	String value=null;
	              	while (it.hasNext()) 
	              	{
	              		param=it.next(); //en n tenemos la clave
	        	      	value=params.get(param).toString();
	        	      	System.out.println("Seteando:"+param+"    "+value);
	        	      	conHttps.setRequestProperty(param, value);
	              	}
                }
                conHttps.setConnectTimeout(timeoutConnection);
                conHttps.setReadTimeout(timeoutConnection);
                conHttps.setRequestProperty("User-agent",userAgent);
                //conHttps.setRequestProperty("Content-Type", "text/plain; charset=utf-8");
                conHttps.setRequestProperty("Accept-Encoding", "gzip, deflate");
                String encoding = conHttps.getContentEncoding();
                Log.log(null,Log.MOD_WEBCRAWLER,Log.LEVEL_MSG, DescargarFuente.class,"formato "+conHttps.getContentType());
                if (encoding != null && encoding.equalsIgnoreCase("gzip"))             return (new GZIPInputStream(conHttps.getInputStream()));
                else if (encoding != null && encoding.equalsIgnoreCase("deflate"))     return (new InflaterInputStream(conHttps.getInputStream(),new Inflater(true)));
                else   return (conHttps.getInputStream());
                
                } 
		    	catch(java.net.SocketTimeoutException timeoutError)
		    	{
		    		Log.log(null,Log.MOD_WEBCRAWLER,Log.LEVEL_ERROR, DescargarFuente.class,"Error timeout de conexion.....");
		    		return null;
		    	}
    			catch (Exception ex) 
                {
                	Log.log(ex,Log.MOD_WEBCRAWLER,Log.LEVEL_ERROR, DescargarFuente.class,"Error en descarga HTTPS");    
                }
    			finally
    			{
    		//		if(con!=null)
    			//		con.disconnect();
    				
    			}
            return null;
     }   

    
    
    
    private String descargaHTTPPOST(String targetURL,Map<String, Object>params)
    {       
    	System.out.println("http post");
    	HttpURLConnection  conn=null;
    	InputStream is =null;
    	try {
        URL url = new URL(targetURL);
        conn = (HttpURLConnection ) url.openConnection();
        //conn.setConnectTimeout(timeoutConnection);
        //conn.setReadTimeout(timeoutConnection);
      	conn.setRequestMethod("POST");
      	conn.setRequestProperty("Accept-Encoding", "gzip, deflate");
        
      	
      	Iterator<String> it = params.keySet().iterator();
      	String param=null;
      	String value=null;
      	while (it.hasNext()) 
      	{
      		param=it.next(); //en n tenemos la clave
	      	value=params.get(param).toString();
	      	System.out.println("Seteando:"+param+"    "+value);
	      	conn.setRequestProperty(param, value);
      	}
      	
      	
      	
        conn.setUseCaches (false);
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setFollowRedirects(true);
        //conn.setInstanceFollowRedirects(true); 


          //Send request
        String urlParameters=params.get("urlParams").toString();
        conn.getOutputStream ().write(urlParameters.getBytes());
        conn.getOutputStream().flush();
        conn.getOutputStream().close();
          //DataOutputStream wr = new DataOutputStream (  conn.getOutputStream ());
          //wr.writeBytes (urlParameters);
          //wr.flush ();
          //wr.close ();

          
          int responseCode = conn.getResponseCode();
          System.out.println("Response Code:"+responseCode);
          //Get Response
          String encoding = conn.getContentEncoding();
          
          if (encoding != null && encoding.equalsIgnoreCase("gzip")) is=(new GZIPInputStream(conn.getInputStream()));
          else if (encoding != null && encoding.equalsIgnoreCase("deflate")) is=(new InflaterInputStream(conn.getInputStream(),new Inflater(true)));
          else    is=(conn.getInputStream());

          

          BufferedReader rd = new BufferedReader(new InputStreamReader(is));
          String line;
          StringBuffer response = new StringBuffer(); 
          while((line = rd.readLine()) != null) {
            response.append(line);
            response.append('\r');
          }
          rd.close();
          
          System.out.println("HTML:\n"+response.toString());
          return response.toString();
          

        } catch (Exception e) {
          e.printStackTrace();
        } finally {

          if(conn != null) {
        	  conn.disconnect(); 
          }
        }
    	return null;
     }

    
    
    private String descargaHTTPSPOST(String targetURL,Map<String, Object>params)
    {       
    	System.out.println("https post");
    	HttpsURLConnection  conn=null;
    	InputStream is =null;
    	try {
        URL url = new URL(targetURL);
        conn = (HttpsURLConnection ) url.openConnection();
        conn.setConnectTimeout(timeoutConnection);
        conn.setReadTimeout(timeoutConnection);
      	conn.setRequestMethod("POST");
      	HttpsURLConnection.setFollowRedirects(true);
      	Iterator<String> it = params.keySet().iterator();
      	String param=null;
      	String value=null;
      	while (it.hasNext()) 
      	{
      		param=it.next(); //en n tenemos la clave
	      	value=params.get(param).toString();
	      	System.out.println("Seteando:"+param+"    "+value);
	      	conn.setRequestProperty(param, value);
      	}
      	
      	
      	String urlParameters=params.get("urlParams").toString();
        conn.setUseCaches (false);
        conn.setDoInput(true);
        conn.setDoOutput(true);
        //conn.setInstanceFollowRedirects(true); 


          //Send request
        conn.getOutputStream ().write(urlParameters.getBytes());
        conn.getOutputStream().flush();
        conn.getOutputStream().close();
          //DataOutputStream wr = new DataOutputStream (  conn.getOutputStream ());
          //wr.writeBytes (urlParameters);
          //wr.flush ();
          //wr.close ();

          
          int responseCode = conn.getResponseCode();
          System.out.println("Response Code:"+responseCode);

          
          //Get Response	
          String encoding = conn.getContentEncoding();
          if (encoding != null && encoding.equalsIgnoreCase("gzip")) is=(new GZIPInputStream(conn.getInputStream()));
          else if (encoding != null && encoding.equalsIgnoreCase("deflate")) is=(new InflaterInputStream(conn.getInputStream(),new Inflater(true)));
          else    is=(conn.getInputStream());

          BufferedReader rd = new BufferedReader(new InputStreamReader(is));
          String line;
          StringBuffer response = new StringBuffer(); 
          while((line = rd.readLine()) != null) {
            response.append(line);
            response.append('\r');
          }
          rd.close();
          
          System.out.println("HTML:\n"+response.toString());
          return response.toString();
          

        } catch (Exception e) {
          e.printStackTrace();
        } finally {

          if(conn != null) {
        	  conn.disconnect(); 
          }
        }
    	return null;
     }

    
    
        
    
   /**Voriginal*/ 
     public String descargarHTML(String link,String metodo,Map<String,Object> params )
      {
          String contenido="";
          try{
        link=validarProtocolo(link);

        Log.log(null,Log.MOD_WEBCRAWLER,Log.LEVEL_MSG, DescargarFuente.class,"descargando: "+link );
        
        InputStream entrada=null;
       
        if(metodo.equalsIgnoreCase("GET"))
	    {
        	if(link.startsWith("https")) entrada= descargaHTTPSGET(link,params);
	        else entrada=descargaHTTPGET(link);
        }
        else
        {
        	if(link.startsWith("https")) return descargaHTTPSPOST(link, params);
	        else return descargaHTTPPOST(link,params);
        	
        	
        }
        String content=getTipoContenido(link);
        

      	contenido= HtmlUtils.getStringFromInputStream(entrada);
      	try{entrada.close(); 	}catch(Exception ex){}
      	try{conHttps.disconnect(); }catch(Exception ex){}
      	try{conHttp.disconnect();}catch(Exception ex){}
        
        Log.log(null,Log.MOD_WEBCRAWLER,Log.LEVEL_SUCESS, DescargarFuente.class,"descarga terminada " );        
          }catch(Exception e)
          {
        	  Log.log(e,Log.MOD_WEBCRAWLER,Log.LEVEL_ERROR, DescargarFuente.class,"Error al descargar HTML");
          }
      
      return contenido;
      }
     	
     
     
  
     
 }